{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "使用随机标签方法做半监督分类，\n",
    "模型采用deeplabp+resnet101。\n",
    "过程：\n",
    "1、使用有监督学习训练，得到模型\n",
    "2、使用1训练好的模型对test_image做预测，得到伪标签\n",
    "3、将2得到的伪标签与训练集合并，然后重新训练\n",
    "4、对test_image做预测，得到新的伪标签\n",
    "5、将4的伪标签放入训练集，重新训练\n",
    "\n",
    "\n",
    "失误：\n",
    "1、中间的数据增强使用旋转增强位置不对，导致生成的图像label边界不对（边界填充数值选取了127.5，相当于注入了噪声。\n",
    "2、等级太低，使用notebookr的时间受限\n",
    "\n",
    "可改进的地方（没时间了）\n",
    "1、使用swim transformer模型\n",
    "2、使用多模型集成学习\n",
    "3、使用其它半监督学习方式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "#解压一PaddleSeg\r\n",
    "!unzip -oq /home/aistudio/PaddleSeg.zip"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "#解压数据集至data/目录\r\n",
    "!unzip -qo data/data95249/train_50k_mask.zip -d data/\r\n",
    "!unzip -oq data/data100087/B榜测试数据集.zip -d data/\r\n",
    "!unzip -oq data/data95249/train_image.zip -d data/"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "# 数据集划分\n",
    "执行一次就行了，之后可直接跳到后面的参数配置及训练"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "系统原有代码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/__init__.py:107: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working\n",
      "  from collections import MutableMapping\n",
      "/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/rcsetup.py:20: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working\n",
      "  from collections import Iterable, Mapping\n",
      "/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/colors.py:53: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working\n",
      "  from collections import Sized\n"
     ]
    }
   ],
   "source": [
    "import sys\r\n",
    "sys.path.append(\"PaddleSeg\")\r\n",
    "import paddleseg\r\n",
    "import paddle\r\n",
    "import numpy as np\r\n",
    "import os\r\n",
    "import matplotlib.pyplot as plt\r\n",
    "from PIL import Image\r\n",
    "from tqdm import tqdm\r\n",
    "import random\r\n",
    "#设置随机数种子\r\n",
    "random.seed(1985)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "def write_txt(file_name, imgs_path, labels_path=None, mode='train', val_pro=0.2):\r\n",
    "    assert mode==\"train\" or mode==\"test\", \"ERROR:mode must be train or test.\"\r\n",
    "    if mode!=\"test\":\r\n",
    "        train_path = []\r\n",
    "        for idx, f_path in enumerate(imgs_path):\r\n",
    "            for i_path in sorted(os.listdir(f_path)):\r\n",
    "                path1 = os.path.join(f_path, i_path) \r\n",
    "                path2 = os.path.join(labels_path[idx], i_path)\r\n",
    "                train_path.append((path1, path2, str(idx)))\r\n",
    "        \r\n",
    "        if val_pro>=0 and val_pro<=1:\r\n",
    "            #打乱数据\r\n",
    "            random.shuffle(train_path)\r\n",
    "            val_len = int(len(train_path)*val_pro)\r\n",
    "            val_path = train_path[:val_len]\r\n",
    "            train_path = train_path[val_len:]\r\n",
    "            with open(file_name[0], 'w') as f:\r\n",
    "                for path in train_path:\r\n",
    "                    f.write(path[0]+\" \"+path[1]+\" \"+path[2]+\"\\n\")\r\n",
    "            with open(file_name[1], 'w') as f:\r\n",
    "                for path in val_path:\r\n",
    "                    f.write(path[0]+\" \"+path[1]+\" \"+path[2]+\"\\n\")  \r\n",
    "            return len(train_path), val_len\r\n",
    "        else:\r\n",
    "            with open(file_name[0], 'w') as f:\r\n",
    "                for path in train_path:\r\n",
    "                    f.write(path[0]+\" \"+path[1]+\" \"+path[2]+\"\\n\") \r\n",
    "            return len(train_path), 0\r\n",
    "    else:\r\n",
    "        with open(file_name, 'w') as f:\r\n",
    "            for path in imgs_path:\r\n",
    "                img_path = os.path.join(test_path, path)\r\n",
    "                f.write(img_path+\"\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "def create_txt(data_root, train_imgs_dir=None, train_labels_dir=None, test_dir=None, val_pro=0.2):\r\n",
    "    if train_imgs_dir is not None:\r\n",
    "        if os.path.exists(\"train.txt\"):\r\n",
    "            os.remove(\"train.txt\")\r\n",
    "        if os.path.exists(\"val.txt\"):\r\n",
    "            os.remove(\"val.txt\")\r\n",
    "        train_imgs_dir = os.path.join(data_root, train_imgs_dir)\r\n",
    "        train_labels_dir = os.path.join(data_root, train_labels_dir)\r\n",
    "        file_names = os.listdir(train_imgs_dir)\r\n",
    "        file_names = sorted(file_names)\r\n",
    "        train_imgs_path, train_labels_path =[], []\r\n",
    "        for na in file_names:\r\n",
    "            train_imgs_path.append(os.path.join(train_imgs_dir, na))\r\n",
    "            train_labels_path.append(os.path.join(train_labels_dir, na))\r\n",
    "        train_len, val_len = write_txt([\"train.txt\", \"val.txt\"], train_imgs_path, train_labels_path, mode='train', val_pro=val_pro)\r\n",
    "        \r\n",
    "        print(\"训练数据整理完毕！训练集长度：{}，验证集长度：{}， 类别数：{}\".format(train_len, val_len, len(file_names)))\r\n",
    "\r\n",
    "    if test_dir is not None:\r\n",
    "        if os.path.exists(\"test.txt\"):\r\n",
    "            os.remove(\"test.txt\")\r\n",
    "        global test_path\r\n",
    "        test_path = os.path.join(data_root, test_dir)\r\n",
    "        test_imgs_path_list = sorted(os.listdir(test_path))\r\n",
    "        write_txt(\"test.txt\", test_imgs_path_list, mode=\"test\")\r\n",
    "        print(\"测试数据整理完毕！测试集长度：{}\".format(len(test_imgs_path_list)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练数据整理完毕！训练集长度：48792，验证集长度：12197， 类别数：501\n",
      "测试数据整理完毕！测试集长度：10989\n"
     ]
    }
   ],
   "source": [
    "def mk_file():\r\n",
    "    data_root = \"data\"\r\n",
    "    train_imgs_dir = \"train_image\"\r\n",
    "    train_labels_dir = \"train_50k_mask\"\r\n",
    "    test_dir = \"test_image\"\r\n",
    "    create_txt(data_root, train_imgs_dir, train_labels_dir, test_dir, val_pro=0.2)\r\n",
    "mk_file()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "#验证一下是否写入正确，可以直接点开文件查看\r\n",
    "#也可以读取文件内容查看\r\n",
    "#以train.txt为例，只看前5行验证\r\n",
    "count = 5\r\n",
    "with open('train.txt', 'r')  as f:\r\n",
    "    for line in f.readlines():\r\n",
    "        print(line)\r\n",
    "        count -= 1\r\n",
    "        if count==0:\r\n",
    "            break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "#随便展示一张图片及其它的label\r\n",
    "%matplotlib inline\r\n",
    "path = line.strip().split(\" \")\r\n",
    "img = plt.imread(path[0], 0) #不管alpha通道\r\n",
    "label = plt.imread(path[1])\r\n",
    "print(\"img shape:\", img.shape)\r\n",
    "print(\"label shape:\", label.shape)\r\n",
    "print(\"classes:\", np.unique(label))\r\n",
    "plt.imshow(img)\r\n",
    "plt.show()\r\n",
    "plt.imshow(label,  cmap='gray')\r\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "# 参数配置及训练\n",
    "在my_deeplabv3.yml中修改参数配置，重启后直接运行下一行代码训练及验证"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "!python PaddleSeg/train.py --config deeplab_v3p.yml --iters 80000 --do_eval --use_vdl  --save_dir /home/aistudio/output_deeplabv3_1 --save_interval 10000"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2021-08-05 10:18:16 [INFO]\t\n",
      "---------------Config Information---------------\n",
      "batch_size: 32\n",
      "loss:\n",
      "  coef:\n",
      "  - 1\n",
      "  types:\n",
      "  - coef:\n",
      "    - 1.0\n",
      "    losses:\n",
      "    - type: CrossEntropyLoss\n",
      "    type: MixedLoss\n",
      "lr_scheduler:\n",
      "  end_lr: 0\n",
      "  learning_rate: 0.01\n",
      "  power: 0.9\n",
      "  type: PolynomialDecay\n",
      "model:\n",
      "  align_corners: true\n",
      "  aspp_out_channels: 256\n",
      "  aspp_ratios:\n",
      "  - 1\n",
      "  - 12\n",
      "  - 24\n",
      "  - 36\n",
      "  backbone:\n",
      "    multi_grid:\n",
      "    - 1\n",
      "    - 2\n",
      "    - 4\n",
      "    output_stride: 8\n",
      "    pretrained: https://bj.bcebos.com/paddleseg/dygraph/resnet101_vd_ssld.tar.gz\n",
      "    type: ResNet101_vd\n",
      "  backbone_indices:\n",
      "  - 0\n",
      "  - 3\n",
      "  num_classes: 2\n",
      "  pretrained: null\n",
      "  type: DeepLabV3P\n",
      "optimizer:\n",
      "  momentum: 0.9\n",
      "  type: sgd\n",
      "  weight_decay: 4.0e-05\n",
      "train_dataset:\n",
      "  dataset_root: /home/aistudio\n",
      "  mode: train\n",
      "  num_classes: 2\n",
      "  train_path: /home/aistudio/train.txt\n",
      "  transforms:\n",
      "  - type: RandomHorizontalFlip\n",
      "  - type: RandomVerticalFlip\n",
      "  - brightness_range: 0.4\n",
      "    contrast_range: 0.4\n",
      "    saturation_range: 0.4\n",
      "    type: RandomDistort\n",
      "  - target_size:\n",
      "    - 256\n",
      "    - 256\n",
      "    type: Resize\n",
      "  - type: Normalize\n",
      "  - type: RandomBlur\n",
      "  type: Dataset\n",
      "val_dataset:\n",
      "  dataset_root: /home/aistudio\n",
      "  mode: val\n",
      "  num_classes: 2\n",
      "  transforms:\n",
      "  - target_size:\n",
      "    - 256\n",
      "    - 256\n",
      "    type: Resize\n",
      "  - type: Normalize\n",
      "  type: Dataset\n",
      "  val_path: /home/aistudio/val.txt\n",
      "------------------------------------------------\n",
      "W0805 10:18:16.802950 17317 device_context.cc:404] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 10.1, Runtime API Version: 10.1\n",
      "W0805 10:18:16.802996 17317 device_context.cc:422] device: 0, cuDNN Version: 7.6.\n",
      "2021-08-05 10:18:21 [INFO]\tLoading pretrained model from https://bj.bcebos.com/paddleseg/dygraph/resnet101_vd_ssld.tar.gz\n",
      "2021-08-05 10:18:23 [INFO]\tThere are 530/530 variables loaded into ResNet_vd.\n",
      "2021-08-05 10:18:23 [INFO]\tNumber of predict images = 10989\n",
      "2021-08-05 10:18:23 [INFO]\tLoading pretrained model from output_deeplabv3_1/best_model/model.pdparams\n",
      "2021-08-05 10:18:25 [INFO]\tThere are 615/615 variables loaded into DeepLabV3P.\n",
      "2021-08-05 10:18:25 [INFO]\tStart to predict...\n",
      "   64/10989 [..............................] - ETA: 24:2"
     ]
    }
   ],
   "source": [
    "#推理\r\n",
    "!python PaddleSeg/predict.py --config deeplab_v3p.yml --model_path output_deeplabv3_1/best_model/model.pdparams --image_path test_image --save_dir output/result_1 #--aug_pred --flip_horizontal --flip_vertical"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "#输出结果\r\n",
    "%cd output/result_1/results\r\n",
    "!zip -r -oq /home/aistudio/pred.zip ./\r\n",
    "%cd /home/aistudio"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "#制做伪标签\r\n",
    "\r\n",
    "!rm -rf /home/aistudio/data/train_50k_mask/test_image/\r\n",
    "!mkdir data/train_50k_mask/test_image\r\n",
    "!cp -r output/result_1/results/* /home/aistudio/data/train_50k_mask/test_image/\r\n",
    "#需转为Png格式，否测出错。\r\n",
    "!cp png_t.py /home/aistudio/data/train_50k_mask/test_image/\r\n",
    "!python png_t.py\r\n",
    "!rm png_t.py\r\n",
    "\r\n",
    "!rm -rf /home/aistudio/output/\r\n",
    "mk_file()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "#代码中断，从最近的iter 70000重启训练\r\n",
    "!python PaddleSeg/train.py --config deeplab_v3p.yml --iters 90000 --do_eval --use_vdl  --resume_model output_deeplabv3_1/iter_70000/ --save_dir /home/aistudio/output_deeplabv3_1 --save_interval 10000\r\n",
    "!python PaddleSeg/predict.py --config deeplab_v3p.yml --model_path output_deeplabv3_1/iter_90000/model.pdparams --image_path test_image --save_dir output/result_1 #--aug_pred --flip_horizontal --flip_vertical"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "#输出结果\r\n",
    "%cd output/result_1/results\r\n",
    "!zip -r -oq /home/aistudio/pred1.zip ./\r\n",
    "%cd /home/aistudio\r\n",
    "#制做伪标签\r\n",
    "!rm -rf /home/aistudio/data/train_50k_mask/test_image/\r\n",
    "!mkdir data/train_50k_mask/test_image\r\n",
    "!cp -r output/result_1/results/* /home/aistudio/data/train_50k_mask/test_image/\r\n",
    "!cp png_t.py /home/aistudio/data/train_50k_mask/test_image/\r\n",
    "!python png_t.py\r\n",
    "!rm png_t.py\r\n",
    "!rm -rf /home/aistudio/output/\r\n",
    "mk_file()\r\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "!python PaddleSeg/train.py --config deeplab_v3p.yml --iters 110000 --do_eval --use_vdl  --resume_model output_deeplabv3_1/iter_90000/ --save_dir /home/aistudio/output_deeplabv3_1 --save_interval 5000\r\n",
    "!python PaddleSeg/predict.py --config deeplab_v3p.yml --model_path output_deeplabv3_1/iter_110000/model.pdparams --image_path test_image --save_dir output/result_1 #--aug_pred --flip_horizontal --flip_vertical\r\n",
    "%cd output/result_1/results\r\n",
    "!zip -r -oq /home/aistudio/pred2.zip ./\r\n",
    "%cd /home/aistudio"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "!rm -rf /home/aistudio/data/train_50k_mask/test_image/\r\n",
    "!mkdir data/train_50k_mask/test_image\r\n",
    "!cp -r output/result_1/results/* /home/aistudio/data/train_50k_mask/test_image/\r\n",
    "!cp png_t.py /home/aistudio/data/train_50k_mask/test_image/\r\n",
    "!python png_t.py\r\n",
    "!rm png_t.py\r\n",
    "!rm -rf /home/aistudio/output/\r\n",
    "mk_file()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "!python PaddleSeg/train.py --config deeplab_v3p.yml --iters 130000 --do_eval --use_vdl  --resume_model output_deeplabv3_1/iter_110000/ --save_dir /home/aistudio/output_deeplabv3_1 --save_interval 5000\r\n",
    "!python PaddleSeg/predict.py --config deeplab_v3p.yml --model_path output_deeplabv3_1/iter_130000/model.pdparams --image_path test_image --save_dir output/result_1 #--aug_pred --flip_horizontal --flip_vertical\r\n",
    "%cd output/result_1/results\r\n",
    "!zip -r -oq /home/aistudio/pred3.zip ./\r\n",
    "%cd /home/aistudio"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "PaddlePaddle 2.1.0 (Python 3.5)",
   "language": "python",
   "name": "py35-paddle1.2.0"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
